
#include "../Main.h"

#include "MenuBar.h"

#include "../Controller/Controller_Main.h"
#include "../Input.h"
#include "../InputKeys.h"
#include "../TextRender.h"
#include "DialogPanel.h"

const u_int uMENU_BAR_TITLE_TEXT_MARGIN = 8;
const u_int uMENU_BAR_TEXT_LIMIT = 64;
const u_int uMENU_BAR_OPEN_MENU_WIDTH = 192;
const u_int uMENU_BAR_OPEN_MENU_ENTRY_HEIGHT = 24;
const u_int uMENU_BAR_OPEN_MENU_DIVIDER_HEIGHT = 2;
const u_int uMENU_BAR_OPEN_MENU_DIVIDER_COL = 0xEEEEEEFF;

DialogPanel* MenuBar::s_pxOpenMenu = 0;
FHandle MenuBar::s_iOpenMenuHandle = INVALID_HANDLE;

class MB_MenuEntry
{
	public:
		
		char m_szName[ uMENU_BAR_TEXT_LIMIT ];
		ButtonPressCallback m_pfnClickCallback;
		void* m_pButtonPressUserData;
		bool m_bIsDivider;
		MenuBar* m_pxMenuBar;
};

class MB_Menu : public Button
{
	public:

		MB_Menu( Widget* pxParent ) : Button( pxParent )
		{
			m_pxMenuEntries = new TypedList< MB_MenuEntry >( true );
			m_iMenuHandle = INVALID_HANDLE;
		}

		virtual ~MB_Menu()
		{
			delete m_pxMenuEntries;
		}

		TypedList< MB_MenuEntry >* m_pxMenuEntries;

		FHandle m_iMenuHandle;
};

MenuBar::MenuBar( Widget* pxParent ) : Panel( pxParent )
{
	m_bCloseOpenMenuNextFrame = false;
}

MenuBar::~MenuBar()
{
	CloseOpenMenu();
}

void MenuBar::Update()
{
	if( m_bCloseOpenMenuNextFrame )
	{
		CloseOpenMenu();
		m_bCloseOpenMenuNextFrame = false;
	}

	if( s_pxOpenMenu )
	{
		// We need to update the open menu ourselves since we have set the menu bar
		// to be modal when it was created.
		s_pxOpenMenu->Update();

		const Input* pxInput = Controller_Main::GetInputHandler();

		if( ( ( pxInput->MouseButtonPressed( INPUT_MOUSE_BUTTON_LEFT ) ||
			    pxInput->MouseButtonPressed( INPUT_MOUSE_BUTTON_RIGHT ) ||
			    pxInput->MouseButtonPressed( INPUT_MOUSE_BUTTON_MIDDLE ) ) &&
			    !s_pxOpenMenu->MouseInWidget() ) ||
			    pxInput->KeyPressed( INPUT_KEY_ESC ) )
		{
			CloseOpenMenu();
		}
		else
		{
			if( m_pxChildren )
			{
				for( int iMenu = 0; iMenu < (int)m_pxChildren->Count(); ++iMenu )
				{
					MB_Menu* pxMenu = reinterpret_cast< MB_Menu* >( m_pxChildren->Get( iMenu ) );
					if( ( pxMenu->m_iMenuHandle != s_iOpenMenuHandle ) && pxMenu->MouseInWidget() )
					{
						MenuTitleClickCallback( pxMenu );
					}
				}
			}
		}

		Panel::Update();
	}
	else
	{
		Panel::Update();
	}
}

FHandle MenuBar::AddMenu( const char* szName )
{
	int iPosX = 0;
	if( m_pxChildren && m_pxChildren->Count() != 0 )
	{
		MB_Menu* pxMenu = reinterpret_cast< MB_Menu* >( m_pxChildren->Get( m_pxChildren->Count() - 1 ) );
		iPosX = ( pxMenu->GetOriginalX() + pxMenu->GetOriginalWidth() );
	}

	MB_Menu* pxMenu = new MB_Menu( this );

	pxMenu->SetLabel( szName );
	pxMenu->SetPosition( m_uPositionX + (u_int)iPosX, m_uPositionY );
	
	u_int uTextWidth, uTextHeight;
	TextRender::SetFont( FONT_SANS_12 );
	TextRender::GetRenderSize( szName, uTextWidth, uTextHeight );

	pxMenu->SetSize( uTextWidth + uMENU_BAR_TITLE_TEXT_MARGIN * 2, GetOriginalHeight() );

	pxMenu->SetFlatStyle( true );
	pxMenu->SetButtonPressCallback( MenuTitleClickCallback, pxMenu );

	pxMenu->m_iMenuHandle = m_pxChildren->Count() - 1;

	return pxMenu->m_iMenuHandle;
}

void MenuBar::AddMenuItem( FHandle iMenuHandle, const char* szName, ButtonPressCallback pfnCallback, void* pUserData )
{
	if( !m_pxChildren || (iMenuHandle >= (FHandle)m_pxChildren->Count()) )
	{
		return;
	}

	MB_Menu* pxMenu = reinterpret_cast< MB_Menu* >( m_pxChildren->Get( iMenuHandle ) );
	if( pxMenu )
	{
		if( pxMenu->m_iMenuHandle != iMenuHandle )
		{
			return; // Cock up
		}
		MB_MenuEntry* pxMenuEntry = new MB_MenuEntry();

		pxMenuEntry->m_pfnClickCallback = pfnCallback;
		pxMenuEntry->m_pButtonPressUserData = pUserData;
		strncpy( pxMenuEntry->m_szName, szName, uMENU_BAR_TEXT_LIMIT );
		pxMenuEntry->m_bIsDivider = false;
		pxMenuEntry->m_pxMenuBar = this;

		pxMenu->m_pxMenuEntries->Add( pxMenuEntry );
	}
}

void MenuBar::AddDivider( FHandle iMenuHandle )
{
	if( iMenuHandle >= (FHandle)m_pxChildren->Count() )
	{
		return;
	}

	MB_Menu* pxMenu = reinterpret_cast< MB_Menu* >( m_pxChildren->Get( iMenuHandle ) );
	if( pxMenu )
	{
		if( pxMenu->m_iMenuHandle != iMenuHandle )
		{
			return; // Cock up
		}

		MB_MenuEntry* pxMenuEntry = new MB_MenuEntry();

		pxMenuEntry->m_pfnClickCallback = 0;
		pxMenuEntry->m_pButtonPressUserData = 0;
		pxMenuEntry->m_szName[0] = 0;
		pxMenuEntry->m_bIsDivider = true;
		pxMenuEntry->m_pxMenuBar = this;

		pxMenu->m_pxMenuEntries->Add( pxMenuEntry );
	}
}

void MenuBar::MenuTitleClickCallback( void* pData )
{
	MB_Menu* pxMenu = reinterpret_cast< MB_Menu* >( pData );
	MenuBar* pxMenuBar = reinterpret_cast< MenuBar* >( pxMenu->GetParent() );
	if( !pxMenuBar )
	{
		return;
	}

	if( s_pxOpenMenu )
	{
		pxMenuBar->CloseOpenMenu();
	}

	// Whatever is the parent of the menu bar needs to be able to accomodate the
	// opened menu panel
	Widget* pxScreen = pxMenuBar->GetParent();
	if( !pxScreen )
	{
		return;
	}

	s_pxOpenMenu = new DialogPanel( pxScreen );
	s_pxOpenMenu->SetPosition( pxMenu->GetResizedX(), pxMenuBar->GetResizedY() + pxMenuBar->GetResizedHeight() );
	s_pxOpenMenu->SetAnchors(  ANCHOR_TOP | ANCHOR_LEFT );
	s_pxOpenMenu->SetHasBorder( true );

	int iPos = 8;

	for( int iMenuEntry = 0; iMenuEntry < (int)pxMenu->m_pxMenuEntries->Count(); ++iMenuEntry )
	{
		MB_MenuEntry* pxMenuEntry = pxMenu->m_pxMenuEntries->Get( iMenuEntry );

		if( pxMenuEntry->m_bIsDivider )
		{
			Panel* pxDivider = new Panel( s_pxOpenMenu );

			pxDivider->SetPosition( s_pxOpenMenu->GetOriginalX() + 8, s_pxOpenMenu->GetOriginalY() + iPos );
			pxDivider->SetSize( uMENU_BAR_OPEN_MENU_WIDTH - 16, uMENU_BAR_OPEN_MENU_DIVIDER_HEIGHT );
			pxDivider->SetColour( uMENU_BAR_OPEN_MENU_DIVIDER_COL );

			iPos += uMENU_BAR_OPEN_MENU_DIVIDER_HEIGHT;
		}
		else
		{
			Button* pxButton = new Button( s_pxOpenMenu );

			pxButton->SetLabel( pxMenuEntry->m_szName );
			pxButton->SetButtonPressCallback( MenuItemClickCallback, pxMenuEntry );
			pxButton->SetPosition( s_pxOpenMenu->GetOriginalX(), s_pxOpenMenu->GetOriginalY() + iPos );
			pxButton->SetSize( uMENU_BAR_OPEN_MENU_WIDTH, uMENU_BAR_OPEN_MENU_ENTRY_HEIGHT );
			pxButton->SetFlatStyle( true );
			pxButton->SetCentreAlignText( false );

			iPos += uMENU_BAR_OPEN_MENU_ENTRY_HEIGHT;
		}
	}

	s_pxOpenMenu->SetSize( uMENU_BAR_OPEN_MENU_WIDTH, iPos + 8 );

	s_iOpenMenuHandle = pxMenu->m_iMenuHandle;

	Controller_Main::AddModal( pxMenuBar );
}

void MenuBar::MenuItemClickCallback( void* pData )
{
	MB_MenuEntry* pxMenuEntry = reinterpret_cast< MB_MenuEntry* >( pData );

	if( !pxMenuEntry )
	{
		return;
	}

	if( pxMenuEntry->m_pfnClickCallback )
	{
		pxMenuEntry->m_pfnClickCallback( pxMenuEntry->m_pButtonPressUserData );
	}

	// Close the open menu
	if( pxMenuEntry->m_pxMenuBar )
	{
		pxMenuEntry->m_pxMenuBar->m_bCloseOpenMenuNextFrame = true;
	}
}


void MenuBar::CloseOpenMenu()
{
	delete s_pxOpenMenu;
	s_pxOpenMenu = 0;
	s_iOpenMenuHandle = INVALID_HANDLE;

	Controller_Main::RemoveModal( this );
}

// eof
